Feat add status cli command#171
Conversation
The lumen index command (the background indexer spawned at SessionStart) created the DB and re-indexed every file from scratch instead of copying an existing sibling-worktree index — only the MCP getOrCreate seeded, and it lost the race to create the DB. runIndexer now seeds from a donor, under the index lock it already holds, before indexing. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
getOrCreate seeded and created a new DB without the index flock that lumen index holds, so both could run SeedFromDonor against the same fresh worktree DB concurrently and corrupt it. getOrCreate now takes the same lock to seed; when a peer holds it, it waits briefly for the peer to publish the DB instead of creating an empty one that clobbers the seed. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Probe every configured server concurrently and print one line per server. With failover, the service counts as healthy when at least one server is reachable, so exit is non-zero only when all are unreachable. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
collectStatus duplicated the git-root → ancestor-index normalization that resolveIndexRoot already encapsulates (and which search uses). Reuse the shared helper instead, removing the duplication, its drift risk, and gaining the symlink resolution status was silently missing. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds donor-based seeding of missing worktree index DBs, a timed create-wait with lock-serialized DB creation to avoid seed races, and a new ChangesIndex seeding, status diagnostics, and creation coordination
Sequence DiagramsequenceDiagram
participant Foreground as Foreground Indexer
participant Lock as Index Lock
participant DB as Index DB File
participant Donor as Donor Worktree
Foreground->>Lock: TryAcquire (DB lock)
alt Lock acquired
Foreground->>DB: Stat (check exists)
alt DB missing
Foreground->>Donor: FindDonorIndex / SeedFromDonor
Donor->>DB: Create seeded DB file
end
else Lock held by peer
Foreground->>DB: Poll for file (createWaitTimeout)
DB->>Foreground: File appears (seeded by peer)
end
Foreground->>Foreground: Open and use DB
🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cmd/stdio.go (1)
520-542: ⚡ Quick winDefer lock release for consistency and panic safety.
The lock is released immediately without
defer, butcmd/index.go:252deferslock.Release()in a similar pattern. While business logic should never panic per guidelines, deferring the release ensures cleanup even ifseedFromDonorencounters an unexpected panic, and makes the code consistent with the existing locking pattern.♻️ Proposed fix
lockPath := indexlock.LockPathForDB(dbPath) lk, lockErr := indexlock.TryAcquire(lockPath) switch { case lockErr == nil && lk != nil: + defer lk.Release() // We own creation. Re-check under the lock — a peer may have created // the DB between our stat above and acquiring the lock. if _, st := os.Stat(dbPath); os.IsNotExist(st) { seedWarning = ic.seedFromDonor(effectiveRoot, modelName, dbPath) } - lk.Release() default:As per coding guidelines: Always defer resource cleanup for database and file handles using
defer Close()(lock resources follow the same pattern).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cmd/stdio.go` around lines 520 - 542, After successfully acquiring the index lock (lockPath via indexlock.TryAcquire returning lk), immediately defer lk.Release() to guarantee the lock is released on panic or early return; remove the explicit lk.Release() call later in the same block so you don't release twice. Keep the re-check of os.Stat(dbPath) and the seed call (ic.seedFromDonor) unchanged, and ensure the default branch still calls ic.waitForDB(dbPath). This mirrors the pattern used around the same lock in the codebase (see the existing defer usage) and ensures deterministic cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@cmd/stdio.go`:
- Around line 520-542: After successfully acquiring the index lock (lockPath via
indexlock.TryAcquire returning lk), immediately defer lk.Release() to guarantee
the lock is released on panic or early return; remove the explicit lk.Release()
call later in the same block so you don't release twice. Keep the re-check of
os.Stat(dbPath) and the seed call (ic.seedFromDonor) unchanged, and ensure the
default branch still calls ic.waitForDB(dbPath). This mirrors the pattern used
around the same lock in the codebase (see the existing defer usage) and ensures
deterministic cleanup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c38dd292-5087-4eaa-ba0e-c98bdccaa962
📒 Files selected for processing (8)
cmd/index.gocmd/seed.gocmd/seed_test.gocmd/status.gocmd/status_test.gocmd/stdio.gocmd/stdio_probe_test.gocmd/stdio_seedrace_test.go
The seed branch released the index lock with an explicit lk.Release(), which leaks the lock if seedFromDonor panics or returns early. Wrap the seed block in an IIFE with defer lk.Release() so cleanup is deterministic while keeping the lock scoped to the seed block. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
errcheck flagged the unchecked write in the status command. Propagate the write error instead of ignoring it. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
Note that this branch includes the commits from #170 because that extracted one common function. |
Adds a
lumen status [path]CLI command that reports embedding-service health and index freshness for a project - the same two checks thedoctorskill runs against the MCP server (health_check+index_status), but standalone andscript-friendly.
Behavior
resolveIndexRoothelper, so it reports DB thatsearchuses.statusnever indexes, seeds, or creates a DB. A missing index DB is reported as "not indexed".0only when at least one server is reachable and the index exists and it is fresh; otherwise1. The "at least one server" rule matches lumen's failover model: the service is usable as long as one backend is up.Notable design points
os.Stat-checked before opening, so inspecting an un-indexed project never creates an empty database. Covered byTestRunStatusMissingIndexNoSideEffect.handleHealthCheckhandler into a sharedprobeEmbeddingService, and path normalization reuses the existingresolveIndexRoothelper rather thanre-rolling the git-root→ancestor logic.
Summary by CodeRabbit
New Features
lumen statusto report embedding service reachability and index freshness with actionable exit codes.Tests